// Copyright Epic Games, Inc. All Rights Reserved.

#include "MaterialProgressBar.h"

#include "Animation/WidgetAnimation.h"
#include "Components/Image.h"
#include "Materials/MaterialInstanceDynamic.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(MaterialProgressBar)

/**
 * 同步属性，初始化进度条状态和材质参数
 */
void UMaterialProgressBar::SynchronizeProperties()
{
	Super::SynchronizeProperties(); // 调用父类同步属性

	if (Image_Bar) // 检查进度条图像控件是否存在
	{
		Image_Bar->SetBrushFromMaterial(bUseStroke ? StrokeMaterial : NoStrokeMaterial); // 根据设置选择材质
		CachedMID = nullptr; // 重置缓存的动态材质
		CachedProgress = -1.0f; // 重置缓存的进度值
		CachedStartProgress = -1.0f; // 重置缓存的起始进度值

#if WITH_EDITORONLY_DATA
		if (IsDesignTime()) // 设计时模式
		{
			SetProgress_Internal(DesignTime_Progress); // 设置设计时进度
		}
#endif

		if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
		{
			if (bOverrideDefaultSegmentEdge) // 检查是否覆盖分段边缘
			{
				MID->SetScalarParameterValue(TEXT("SegmentEdge"), SegmentEdge); // 设置分段边缘参数
			}

			if (bOverrideDefaultSegments) // 检查是否覆盖分段数
			{
				MID->SetScalarParameterValue(TEXT("Segments"), (float)Segments); // 设置分段数参数
			}

			if (bOverrideDefaultFillEdgeSoftness) // 检查是否覆盖填充边缘柔化
			{
				MID->SetScalarParameterValue(TEXT("FillEdgeSoftness"), FillEdgeSoftness); // 设置填充边缘柔化参数
			}

			if (bOverrideDefaultGlowEdge) // 检查是否覆盖发光边缘
			{
				MID->SetScalarParameterValue(TEXT("GlowEdge"), GlowEdge); // 设置发光边缘参数
			}

			if (bOverrideDefaultGlowSoftness) // 检查是否覆盖发光柔化
			{
				MID->SetScalarParameterValue(TEXT("GlowSoftness"), GlowSoftness); // 设置发光柔化参数
			}

			if (bOverrideDefaultOutlineScale) // 检查是否覆盖轮廓缩放
			{
				MID->SetScalarParameterValue(TEXT("OutlineScale"), OutlineScale); // 设置轮廓缩放参数
			}
		}

		if (bOverrideDefaultColorA) // 检查是否覆盖颜色A
		{
			SetColorA_Internal(CachedColorA); // 设置颜色A
		}

		if (bOverrideDefaultColorB) // 检查是否覆盖颜色B
		{
			SetColorB_Internal(CachedColorB); // 设置颜色B
		}

		if (bOverrideDefaultColorBackground) // 检查是否覆盖背景颜色
		{
			SetColorBackground_Internal(CachedColorBackground); // 设置背景颜色
		}
	}
}

#if WITH_EDITOR
/**
 * 控件重建时的处理，用于编辑器模式下获取默认材质参数
 */
void UMaterialProgressBar::OnWidgetRebuilt()
{
	Super::OnWidgetRebuilt(); // 调用父类重建方法

	if (IsDesignTime() && Image_Bar) // 设计时模式且图像控件存在
	{
		if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
		{
			if (!bOverrideDefaultColorA) // 如果没有覆盖颜色A
			{
				MID->GetVectorParameterValue(TEXT("ColorA"), CachedColorA); // 从材质获取颜色A默认值
			}

			if (!bOverrideDefaultColorB) // 如果没有覆盖颜色B
			{
				MID->GetVectorParameterValue(TEXT("ColorB"), CachedColorB); // 从材质获取颜色B默认值
			}

			if (!bOverrideDefaultColorBackground) // 如果没有覆盖背景颜色
			{
				MID->GetVectorParameterValue(TEXT("Unfilled Color"), CachedColorBackground); // 从材质获取背景颜色默认值
			}

			if (!bOverrideDefaultSegmentEdge) // 如果没有覆盖分段边缘
			{
				MID->GetScalarParameterValue(TEXT("SegmentEdge"), SegmentEdge); // 从材质获取分段边缘默认值
			}

			if (!bOverrideDefaultSegments) // 如果没有覆盖分段数
			{
				float SegmentsFloat; // 临时浮点变量
				MID->GetScalarParameterValue(TEXT("Segments"), SegmentsFloat); // 从材质获取分段数默认值
				Segments = FMath::TruncToInt(SegmentsFloat); // 转换为整数
			}

			if (!bOverrideDefaultFillEdgeSoftness) // 如果没有覆盖填充边缘柔化
			{
				MID->GetScalarParameterValue(TEXT("FillEdgeSoftness"), FillEdgeSoftness); // 从材质获取填充边缘柔化默认值
			}

			if (!bOverrideDefaultGlowEdge) // 如果没有覆盖发光边缘
			{
				MID->GetScalarParameterValue(TEXT("GlowEdge"), GlowEdge); // 从材质获取发光边缘默认值
			}

			if (!bOverrideDefaultGlowSoftness) // 如果没有覆盖发光柔化
			{
				MID->GetScalarParameterValue(TEXT("GlowSoftness"), GlowSoftness); // 从材质获取发光柔化默认值
			}

			if (!bOverrideDefaultOutlineScale) // 如果没有覆盖轮廓缩放
			{
				MID->GetScalarParameterValue(TEXT("OutlineScale"), OutlineScale); // 从材质获取轮廓缩放默认值
			}
		}
	}
}
#endif

/**
 * 动画完成回调
 * @param Animation 完成的动画对象
 */
void UMaterialProgressBar::OnAnimationFinished_Implementation(const UWidgetAnimation* Animation)
{
	Super::OnAnimationFinished_Implementation(Animation); // 调用父类动画完成方法

	if (BoundAnim_FillBar == Animation) // 检查是否是填充动画
	{
		OnFillAnimationFinished.Broadcast(); // 广播填充动画完成事件
	}
}

/**
 * 设置进度条进度
 * @param Progress 进度值（0-1）
 */
void UMaterialProgressBar::SetProgress(float Progress)
{
	if (CachedProgress != Progress) // 检查进度值是否变化
	{
		SetProgress_Internal(Progress); // 调用内部设置进度方法
	}
}

/**
 * 设置进度条起始进度
 * @param StartProgress 起始进度值（0-1）
 */
void UMaterialProgressBar::SetStartProgress(float StartProgress)
{
	if (CachedStartProgress != StartProgress) // 检查起始进度值是否变化
	{
		SetStartProgress_Internal(StartProgress); // 调用内部设置起始进度方法
	}
}

/**
 * 设置颜色A
 * @param ColorA 颜色值
 */
void UMaterialProgressBar::SetColorA(FLinearColor ColorA)
{
	if (CachedColorA != ColorA) // 检查颜色A是否变化
	{
		SetColorA_Internal(ColorA); // 调用内部设置颜色A方法
	}
}

/**
 * 设置颜色B
 * @param ColorB 颜色值
 */
void UMaterialProgressBar::SetColorB(FLinearColor ColorB)
{
	if (CachedColorB != ColorB) // 检查颜色B是否变化
	{
		SetColorB_Internal(ColorB); // 调用内部设置颜色B方法
	}
}

/**
 * 设置背景颜色
 * @param ColorBackground 背景颜色值
 */
void UMaterialProgressBar::SetColorBackground(FLinearColor ColorBackground)
{
	if (CachedColorBackground != ColorBackground) // 检查背景颜色是否变化
	{
		SetColorBackground_Internal(ColorBackground); // 调用内部设置背景颜色方法
	}
}

/**
 * 从指定起始点动画填充进度条
 * @param Start 起始进度
 * @param End 结束进度
 * @param AnimSpeed 动画速度
 */
void UMaterialProgressBar::AnimateProgressFromStart(float Start, float End, float AnimSpeed)
{
	SetStartProgress(Start); // 设置起始进度
	SetProgress(End); // 设置结束进度
	PlayAnimation(BoundAnim_FillBar, 0.0f, 1, EUMGSequencePlayMode::Forward, AnimSpeed); // 播放填充动画
}

/**
 * 从当前进度动画填充到指定进度
 * @param End 结束进度
 * @param AnimSpeed 动画速度
 */
void UMaterialProgressBar::AnimateProgressFromCurrent(float End, float AnimSpeed)
{
	if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
	{
		const float CurrentStart = MID->K2_GetScalarParameterValue(TEXT("StartProgress")); // 获取当前起始进度
		const float CurrentEnd = MID->K2_GetScalarParameterValue(TEXT("Progress")); // 获取当前结束进度
		const float CurrentFill = MID->K2_GetScalarParameterValue(TEXT("FillAmount")); // 获取当前填充量
		const float NewStart = FMath::Lerp(CurrentStart, CurrentEnd, CurrentFill); // 计算新的起始进度
		AnimateProgressFromStart(NewStart, End, AnimSpeed); // 从新起始点开始动画
	}
}

/**
 * 内部设置进度
 * @param Progress 进度值
 */
void UMaterialProgressBar::SetProgress_Internal(float Progress)
{
	if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
	{
		CachedProgress = Progress; // 更新缓存进度
		MID->SetScalarParameterValue(TEXT("Progress"), CachedProgress); // 设置材质进度参数
	}
}

/**
 * 内部设置起始进度
 * @param StartProgress 起始进度值
 */
void UMaterialProgressBar::SetStartProgress_Internal(float StartProgress)
{
	if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
	{
		CachedStartProgress = StartProgress; // 更新缓存起始进度
		MID->SetScalarParameterValue(TEXT("StartProgress"), CachedStartProgress); // 设置材质起始进度参数
	}
}

/**
 * 内部设置颜色A
 * @param ColorA 颜色值
 */
void UMaterialProgressBar::SetColorA_Internal(FLinearColor ColorA)
{
	if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
	{
		CachedColorA = ColorA; // 更新缓存颜色A
		MID->SetVectorParameterValue(TEXT("ColorA"), CachedColorA); // 设置材质颜色A参数
	}
}

/**
 * 内部设置颜色B
 * @param ColorB 颜色值
 */
void UMaterialProgressBar::SetColorB_Internal(FLinearColor ColorB)
{
	if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
	{
		CachedColorB = ColorB; // 更新缓存颜色B
		MID->SetVectorParameterValue(TEXT("ColorB"), CachedColorB); // 设置材质颜色B参数
	}
}

/**
 * 内部设置背景颜色
 * @param ColorBackground 背景颜色值
 */
void UMaterialProgressBar::SetColorBackground_Internal(FLinearColor ColorBackground)
{
	if (UMaterialInstanceDynamic* MID = GetBarDynamicMaterial()) // 获取动态材质实例
	{
		CachedColorBackground = ColorBackground; // 更新缓存背景颜色
		MID->SetVectorParameterValue(TEXT("Unfilled Color"), CachedColorBackground); // 设置材质背景颜色参数
	}
}

/**
 * 获取进度条动态材质实例
 * @return 动态材质实例指针
 */
UMaterialInstanceDynamic* UMaterialProgressBar::GetBarDynamicMaterial() const
{
	if (!CachedMID) // 检查是否已缓存
	{
		CachedMID = Image_Bar->GetDynamicMaterial(); // 从图像控件获取动态材质
	}

	return CachedMID; // 返回缓存的动态材质实例
}